package cn.tedu.csmall.product.controller;

import cn.tedu.csmall.product.pojo.param.AlbumAddNewParam;
import cn.tedu.csmall.product.pojo.param.AlbumUpdateInfoParam;
import cn.tedu.csmall.product.pojo.vo.AlbumListItemVO;
import cn.tedu.csmall.product.pojo.vo.AlbumStandardVO;
import cn.tedu.csmall.commons.pojo.vo.PageData;
import cn.tedu.csmall.commons.security.LoginPrincipal;
import cn.tedu.csmall.product.service.IAlbumService;
import cn.tedu.csmall.commons.web.JsonResult;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.constraints.Range;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.validation.Valid;

/**
 * 处理相册相关请求的控制器类
 *
 * @author java@tedu.cn
 * @version 0.0.1
 */
@Slf4j
@RestController
@RequestMapping("/albums")
@Validated
@Api(tags = "04.相册管理模块") //此注解用于Knife4j的API文档显示内容的配置
public class AlbumController {

    @Autowired
    private IAlbumService albumService;

    public AlbumController() {
        log.debug("创建控制器类对象：AlbumController");
    }

    // http://localhost:9180/albums/add-new
    //@RequestMapping(value = "/add-new",method = RequestMethod.POST) //注解内设置参数将请求方式限制为POST
    @PostMapping("/add-new") //用此组合注解也可以将请求方式限制为POST
    @PreAuthorize("hasAuthority('/pms/album/add-new')") //添加权限
    @ApiOperation("添加相册") //此注解添加在处理请求的方法上，通过此注解的value属性，可以配置Knife4j的API文档业务功能名称
    @ApiOperationSupport(order = 100) //此注解用于将@ApiOperation的属性值进行排序，order值越大越靠后
    //@ApiIgnore：添加在请求参数上，表示API文档将忽略此请求参数，例如:@ApiIgnore HttpSession session
    public JsonResult addNew(@Valid AlbumAddNewParam albumAddNewParam) {
        log.debug("开始处理【添加相册】的请求，参数：{}", albumAddNewParam);
        albumService.addNew(albumAddNewParam);

        //改造如下4行代码的解决方案
//        JsonResult jsonResult = new JsonResult();
//        jsonResult.setState(1);
//        jsonResult.setMessage("添加成功！");
//        return jsonResult;
        //方案1，在JsonResult类中添加有参构造，然后写如下代码
        // return new JsonResult(1, "添加成功");
        //方案2，调整JsonResult类中的setter方法，代码参考JsonResult类注释代码，然后写的代码跟方案3相同
        //方案3，在JsonResult类中添加注解@Accessors(chain = true)，然后写如下代码，也称为链式方法
        //return new JsonResult().setState(1).setMessage("添加成功！");
        //方案4，在JsonResult类中写静态方法，new对象，然后设置setter，返回对象，再写如下代码
        return JsonResult.ok();
    }

    // http://localhost:9180/albums/xxx/delete
    @PostMapping("/{id:[0-9]+}/delete")
    @PreAuthorize("hasAuthority('/pms/album/delete')")
    @ApiOperation("根据ID删除相册")
    @ApiOperationSupport(order = 200)
    /*
    @ApiImplicitParam：添加在处理请求的方法上，用于对未封装的请求参数进行描述，注意，此注解必须配置name属性，取值为方法的参数名，
    然后，结合此注解的value属性对参数进行描述，此注解还有与@ApiModelProperty相同的一些属性，例如required、example等，还可以通过dataType指定数据类型
    @ApiImplicitParams：添加在处理请求的方法上，当有多个@ApiImplictParam需要被配置时，应该将它们作为当前@ApiImplicitParams的属性值
    @RequestParam注解作用是解决doc文档调试的输入框显示异常的bug，没有什么实际的作用
     */
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "相册ID", required = true, dataType = "long")
    })
    public JsonResult delete(@Range(min = 1, message = "根据ID删除相册失败，请提交合法的ID值")
                             @PathVariable Long id) {
        log.debug("开始处理【根据ID删除相册】的请求，参数：{}", id);
        albumService.delete(id);
        return JsonResult.ok();
    }

    // http://localhost:9180/albums/xxx/update
    @PostMapping("/{id:[0-9]+}/update")
    @PreAuthorize("hasAuthority('/pms/album/update')")
    @ApiOperation("修改相册")
    @ApiOperationSupport(order = 300)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "相册ID", required = true, dataType = "long")
    })
    public JsonResult updateInfoById(@PathVariable @Range(min = 1, message = "请提交有效的相册ID值！") Long id,
                                     @Valid AlbumUpdateInfoParam albumUpdateInfoParam) {
        log.debug("开始处理【修改相册详情】的业务，参数：{}", albumUpdateInfoParam);
        albumService.updateInfoById(id, albumUpdateInfoParam);
        return JsonResult.ok();
    }

    // http://localhost:9180/albums/xxx
    @GetMapping("/{id:[0-9]+}")
    @PreAuthorize("hasAuthority('/pms/album/read')")
    @ApiOperation("根据ID查询相册详情")
    @ApiOperationSupport(order = 410)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "相册ID", required = true, dataType = "long")
    })
    public JsonResult getStandardById(@Range(min = 1, message = "根据ID查询相册详情失败，请提交合法的ID值！")
                                      @PathVariable Long id) {
        log.debug("开始处理【根据ID查询相册详情】的请求，参数：{}", id);
        AlbumStandardVO result = albumService.getStandardById(id);
        return JsonResult.ok(result);
    }

    // http://localhost:9180/albums
    @GetMapping("")
    @PreAuthorize("hasAuthority('/pms/album/read')")
    @ApiOperation("查询相册列表")
    @ApiOperationSupport(order = 420)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pageNum", value = "页码", paramType = "query")
    })
    public JsonResult list(@Range(min = 1, message = "查询相册列表失败，请提供正确的页码值！") Integer pageNum,
                           @ApiIgnore @AuthenticationPrincipal LoginPrincipal loginPrincipal) {
        log.debug("开始处理【查询相册列表】的请求，页码：{}", pageNum);
        log.debug("当事人：{}", loginPrincipal);
        if (pageNum == null || pageNum < 1) {
            pageNum = 1;
        }
        PageData<AlbumListItemVO> pageData = albumService.list(pageNum);
        return JsonResult.ok(pageData);
    }

}
